home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / Kibitz / DoEvent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  16.8 KB  |  670 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        doevent.c
  5. ** Written by:  Eric Soldan
  6. **
  7. ** Copyright © 1990-1992 Apple Computer, Inc.
  8. ** All rights reserved. */
  9.  
  10.  
  11.  
  12. /*****************************************************************************/
  13.  
  14.  
  15.  
  16. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  17. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  18. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  19.  
  20. #ifndef __AEUTILS__
  21. #include <AEUtils.h>
  22. #endif
  23.  
  24. #ifndef __DESK__
  25. #include <Desk.h>
  26. #endif
  27.  
  28. #ifndef __DISKINIT__
  29. #include <DiskInit.h>
  30. #endif
  31.  
  32. #ifndef __ERRORS__
  33. #include <Errors.h>
  34. #endif
  35.  
  36. #ifndef __MENUS__
  37. #include <Menus.h>
  38. #endif
  39.  
  40. #ifndef __OSEVENTS__
  41. #include <OSEvents.h>
  42. #endif
  43.  
  44. #ifndef __RESOURCES__
  45. #include <Resources.h>
  46. #endif
  47.  
  48. #ifndef __TEXTEDITCONTROL__
  49. #include <TextEditControl.h>
  50. #endif
  51.  
  52. #ifndef __TOOLUTILS__
  53. #include <ToolUtils.h>
  54. #endif
  55.  
  56. #ifndef __UTILITIES__
  57. #include <Utilities.h>
  58. #endif
  59.  
  60.  
  61.  
  62. /*****************************************************************************/
  63.  
  64.  
  65.  
  66. extern Cursor    *gCurrentCursor;
  67.  
  68. unsigned long    gStatusTime;
  69. Boolean            gAlertTimeout, gComputerResigns;
  70.  
  71.  
  72.  
  73. /*****************************************************************************/
  74. /*****************************************************************************/
  75.  
  76.  
  77.  
  78. /* Do the right thing for an event.  Determine what kind of event it is, and
  79. ** call the appropriate routines. */
  80.  
  81. #pragma segment Main
  82. void    DoEvent(EventRecord *event)
  83. {
  84.     short            part, err;
  85.     WindowPtr        window;
  86.     char            key;
  87.     Point            aPoint;
  88.     FileRecHndl        frHndl;
  89.     ControlHandle    ctl;
  90.     long            tick;
  91.     Rect            boardRct;
  92.     short            retval, width, dir;
  93.  
  94.     switch(event->what) {
  95.  
  96.         case mouseDown:
  97.             gCurrentCursor = nil;
  98.                 /* No shortcuts when we recalculate the cursor region. */
  99.  
  100.             part = FindWindow(event->where, &window);
  101.             if (part != inContent) DoSetCursor(&qd.arrow);
  102.  
  103.             switch(part) {
  104.  
  105.                 case inContent:
  106.                     if (window != FrontWindow()) {
  107.                         SelectWindow(window);
  108.                         if (IsAppWindow(window)) {
  109.                             DoUpdate(window);
  110.                             boardRct = GlobalBoardRect(window);
  111.                             if (PtInRect(event->where, &boardRct))
  112.                                 DoEvent(event);
  113.                         }
  114.                                     /* Do first click if over board. */
  115.                     } else
  116.                         DoContentClick(window, event);
  117.                     break;
  118.  
  119.                 case inDrag:            
  120.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  121.                     break;        /* Pass screenBits.bounds to
  122.                                 ** get all gDevices. */
  123.  
  124.                 case inGoAway:
  125.                     if (TrackGoAway(window, event->where)) {
  126.                         CloseOneWindow(window, iClose);
  127.                     }
  128.                     break;
  129.  
  130.                 case inGrow:
  131.                     break;
  132.  
  133.                 case inMenuBar:        /* Process mouse menu command (if any). */
  134.                     AdjustMenus();
  135.                     DoMenuCommand(MenuSelect(event->where), event);
  136.                     break;
  137.  
  138.                 case inSysWindow:    /* Let the system handle the mouseDown. */
  139.                     SystemClick(event, window);
  140.                     break;
  141.  
  142.                 case inZoomIn:
  143.                 case inZoomOut:
  144.                     if (TrackBox(window, event->where, part)) {
  145.                         width = window->portRect.right - window->portRect.left;
  146.                         if (width == rWindowWidth) width = rJustBoardWindowWidth;
  147.                         else                       width = rWindowWidth;
  148.                         ZoomToWindowDevice(window, width, rWindowHeight, inZoomOut, true);
  149.                     }
  150.                     break;
  151.  
  152.             }
  153.             break;
  154.  
  155.         case activateEvt:
  156.             gCurrentCursor = nil;        /* No shortcuts when we recalculate the cursor region. */
  157.             DoActivate((WindowPtr)event->message, (event->modifiers & activeFlag));
  158.             break;
  159.  
  160.         case autoKey:
  161.         case keyDown:                    /* Check for menukey equivalents. */
  162.             key = event->message & charCodeMask;
  163.             if (event->modifiers & cmdKey) {        /* Command key down. */
  164.                 if (event->what == keyDown) {
  165.                     AdjustMenus();
  166.                         /* Enable/disable/check menu items properly. */
  167.                     DoMenuCommand(MenuKey(key), event);
  168.                 }
  169.             }
  170.             else {
  171.                 if (!IsAppWindow(window = FrontWindow())) break;
  172.                 frHndl = (FileRecHndl)GetWRefCon(window);
  173.                 if (key == 0x03) {
  174.                     ctl = (*frHndl)->doc.sendMessage;
  175.                     if (!(*ctl)->contrlHilite) {
  176.                         HiliteControl(ctl, 1);
  177.                         tick = TickCount();
  178.                         while (TickCount() < tick + 10);
  179.                         HiliteControl(ctl, 0);
  180.                         SendMssg(frHndl, kTextMssg);
  181.                     }
  182.                 }
  183.                 else {
  184.                     if (event->modifiers & optionKey) {
  185.                         dir = 0;
  186.                         if ((key == chLeft)  || (key == chUp))   dir = -1;
  187.                         if ((key == chRight) || (key == chDown)) dir = 1;
  188.                         if (dir) {
  189.                             SetFilePort(frHndl);
  190.                             RepositionBoard(frHndl, (*frHndl)->doc.gameIndex + dir, true);
  191.                             ImageDocument(frHndl, true);
  192.                             AdjustGameSlider(frHndl);
  193.                             if ((*frHndl)->doc.twoPlayer) SendGame(frHndl, kResync, nil);
  194.                         }
  195.                         return;
  196.                     }
  197.                     if (retval = CTEKey(window, event)) {
  198.                         if (retval == 2) (*frHndl)->fileState.docDirty = true;
  199.                             /* Out-box was edited, so dirty document. */
  200.                         AdjustMenus();        /* Avoid unnecessary DoCursor() and speed */
  201.                         return;                /* up TextEdit entry. */
  202.                     }
  203.                 }
  204.             }
  205.             break;
  206.  
  207.         case diskEvt:
  208.             gCurrentCursor = nil;
  209.                 /* No shortcuts when we recalculate the cursor region. */
  210.  
  211.             if (HiWord(event->message) != noErr) {
  212.                 SetPt(&aPoint, kDILeft, kDITop);
  213.                 err = DIBadMount(aPoint, event->message);
  214.             }
  215.             break;        /* It is not a bad idea to at least call DIBadMount
  216.                         ** in response to a diskEvt, so that the user can
  217.                         ** format a floppy.
  218.                         */
  219.         case kHighLevelEvent:
  220.             gCurrentCursor = nil;
  221.                 /* No shortcuts when we recalculate the cursor region. */
  222.  
  223.             DoHighLevelEvent(event);
  224.             break;
  225.  
  226.         case kOSEvent:
  227.             gCurrentCursor = nil;
  228.                 /* No shortcuts when we recalculate the cursor region. */
  229.  
  230.             switch ((event->message >> 24) & 0x0FF) {
  231.                     /* Must logical and with 0x0FF to get only low byte. */
  232.                     /* High byte of message. */
  233.  
  234.                 case kMouseMovedMessage:
  235.                     break;
  236.  
  237.                 case kSuspendResumeMessage:
  238.                         /* Suspend/resume is also an activate/deactivate. */
  239.                     gInBackground = !((event->message) & kResumeMask);
  240.                     CTEConvertClipboard((event->message) & convertClipboardFlag, !gInBackground);
  241.                     DoActivate(FrontWindow(), !gInBackground);
  242.                     break;
  243.             }
  244.             break;
  245.  
  246.         case updateEvt:
  247.             DoUpdate((WindowPtr)event->message);
  248.             break;
  249.  
  250.     }
  251.  
  252.     DoCursor();
  253.     AdjustMenus();
  254. }
  255.  
  256.  
  257.  
  258. /*****************************************************************************/
  259.  
  260.  
  261.  
  262. /* This is called when a window is activated or deactivated. */
  263.  
  264. #pragma segment Main
  265. void    DoActivate(WindowPtr window, Boolean becomingActive)
  266. {
  267.     FileRecHndl        frHndl;
  268.     short            hilite;
  269.     ControlHandle    ctl;
  270.  
  271.     NotifyCancel();
  272.  
  273.     if (IsAppWindow(window)) {
  274.  
  275.         frHndl = (FileRecHndl)GetWRefCon(window);
  276.  
  277.         SetPort(window);
  278.         SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  279.  
  280.         hilite = 0;
  281.         if (!becomingActive) hilite = 255;
  282.  
  283.         HiliteControl((*frHndl)->doc.gameSlider, hilite);
  284.         HiliteControl((*frHndl)->doc.resign, hilite);
  285.         HiliteControl((*frHndl)->doc.draw, hilite);
  286.  
  287.         if (!(*frHndl)->doc.twoPlayer) hilite = 255;
  288.  
  289.         HiliteControl(ctl = (*frHndl)->doc.sendMessage, hilite);
  290.         OutlineControl(ctl);
  291.         HiliteControl((*frHndl)->doc.beepOnMove, hilite);
  292.         HiliteControl((*frHndl)->doc.beepOnMssg, hilite);
  293.  
  294.         if (!SoundInputAvaliable()) hilite = 255;
  295.         HiliteControl((*frHndl)->doc.record, hilite);
  296.         if (!(*frHndl)->doc.sound) hilite = 255;
  297.         HiliteControl((*frHndl)->doc.sendSnd, hilite);
  298.  
  299.         if (!(*frHndl)->doc.arrangeBoard) CTEWindActivate(window);
  300.  
  301.         DoDrawControls(window, true);
  302.         SetOrigin(0, 0);
  303.     }
  304. }
  305.  
  306.  
  307.  
  308. /*****************************************************************************/
  309.  
  310.  
  311.  
  312. /* This is called when an update event is received for a window.  It calls
  313. ** ImageDocument to draw the contents of an application window.  As an
  314. ** effeciency measure that does not have to be followed, it calls the drawing
  315. ** routine only if the visRgn is non-empty.  This will handle situations where
  316. ** calculations for drawing or drawing itself is very time-consuming. */
  317.  
  318. #pragma segment Main
  319. void    DoUpdate(WindowPtr window)
  320. {
  321.     if (IsAppWindow(window)) {
  322.         BeginUpdate(window);                /* This sets up the visRgn. */
  323.         if (!EmptyRgn(window->visRgn)) {    /* Draw if updating needs doing. */
  324.             SetPort(window);
  325.             ImageDocument((FileRecHndl)GetWRefCon(window), false);
  326.         }
  327.         EndUpdate(window);
  328.     }
  329. }
  330.  
  331.  
  332.  
  333. /*****************************************************************************/
  334.  
  335.  
  336.  
  337. /* This is called when a mouse-down event occurs in the content of a window.
  338. ** Other applications might want to call FindControl, TEClick, etc., to
  339. ** further process the click. */
  340.  
  341. #pragma segment Main
  342. void    DoContentClick(WindowPtr window, EventRecord *event)
  343. {
  344.     Boolean            invertBoard, legalMove;
  345.     short            fromRow, fromCol, toRow, toCol, i, myColor;
  346.     short            fromSq, toSq, promotion, piece, item;
  347.     short            numLegalMoves, part, twoPlayer, whosMove;
  348.     OSErr            err;
  349.     long            ref;
  350.     Point            clickLoc, releaseLoc;
  351.     Rect            boardRect, fromRect;
  352.     FileRecHndl        frHndl;
  353.     MoveListHndl    legalMoves;
  354.     DialogPtr        promoteDialog;
  355.     short            itemType, ctlNum, val, action;
  356.     Handle            itemHndl;
  357.     Rect            itemRect;
  358.     ControlHandle    ctlHit;
  359.     EventRecord        option;
  360.  
  361.     if (!IsAppWindow(window)) return;
  362.  
  363.     frHndl = (FileRecHndl)GetWRefCon(window);
  364.     SetPort(window);
  365.     SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  366.  
  367.     twoPlayer = (*frHndl)->doc.twoPlayer;
  368.  
  369.     clickLoc = event->where;
  370.     GlobalToLocal(&clickLoc);
  371.  
  372.     if (CTEClick(window, event, &action)) {
  373.         SetOrigin(0, 0);
  374.         return;
  375.     }
  376.         /* If TextEdit control handled the click, we are done. */
  377.  
  378.     if (part = FindControl(clickLoc, window, &ctlHit)) {
  379.         ctlNum = ref = GetCRefCon(ctlHit);
  380.         if ((ref) && (ref < 10)) {
  381.             if (TrackControl(ctlHit, clickLoc, nil)) {
  382.                 switch (ctlNum) {
  383.                     case 1:
  384.                         SendMssg(frHndl, kTextMssg);
  385.                         break;
  386.                     case 2:
  387.                     case 3:
  388.                         SetCtlValue(ctlHit, val = (GetCtlValue(ctlHit) ^ 1));
  389.                         if (val)
  390.                             if ((event->modifiers) & optionKey) SendMssg(frHndl, kBeepMssg);
  391.                         break;
  392.                     case 4:
  393.                     case 5:
  394.                         SetCtlValue(ctlHit, 1);
  395.                         SetCtlValue((*frHndl)->doc.wbStart[5 - ctlNum], 0);
  396.                         (*frHndl)->doc.startColor = ctlNum - 4;
  397.                         break;
  398.                     case 6:
  399.                         EndTheGame(frHndl, kWhiteResigns + (*frHndl)->doc.myColor);
  400.                         UpdateGameStatus(frHndl);
  401.                         if (twoPlayer) {
  402.                             SendGame(frHndl, kIsMove, nil);
  403.                                 /* Show the dialog at the other end. */
  404.                             SendGame(frHndl, kResync, nil);
  405.                                 /* Make sure that simultaneous hits on the
  406.                                 ** resign button are taken care of. */
  407.                         }
  408.                         break;
  409.                     case 7:
  410.                         i = ((*frHndl)->doc.drawBtnState ^ 0x02);
  411.                         if (!twoPlayer) i = 0x06;
  412.                         if (i >= 0x06) EndTheGame(frHndl, kDrawGame);
  413.                         DrawButtonTitle(frHndl, i);
  414.                         if (twoPlayer) {
  415.                             SendGame(frHndl, kIsMove, nil);
  416.                                 /* Show the dialog at the other end. */
  417.                             SendGame(frHndl, kResync, nil);
  418.                                 /* Make sure that simultaneous hits on the
  419.                                 ** draw button are taken care of. */
  420.                         }
  421.                         break;
  422.                     case 8:
  423.                         err = RecordSound(frHndl);
  424.                         if ((err) && (err != userCanceledErr))
  425.                             Alert(rErrorAlert, (ModalFilterProcPtr)AlertFilter);
  426.                         break;
  427.                     case 9:
  428.                         SendMssg(frHndl, kSoundMssg);
  429.                         break;
  430.                 }
  431.             }
  432.         }
  433.         SetOrigin(0, 0);
  434.  
  435.         if (ctlHit == (*frHndl)->doc.gameSlider)
  436.             TrackControl(ctlHit, clickLoc, nil);
  437.  
  438.         return;
  439.     }
  440.  
  441.     if ((*frHndl)->fileState.readOnly) {
  442.         SetOrigin(0, 0);
  443.         return;
  444.     }                    /* Don't allow changes if read-only. */
  445.  
  446.     if ((*frHndl)->doc.arrangeBoard) {
  447.         DoArrangeBoard(frHndl, event, clickLoc);
  448.         return;
  449.     }
  450.  
  451.     SetOrigin(0, 0);
  452.  
  453.     invertBoard = (*frHndl)->doc.invertBoard;
  454.  
  455.     boardRect = BoardRect();
  456.     if (!PtInRect(clickLoc, &boardRect)) return;
  457.  
  458.     fromRow = (clickLoc.v - kBoardVOffset) / kBoardSqSize;
  459.     fromCol = (clickLoc.h - kBoardHOffset) / kBoardSqSize;
  460.     fromRect.top    = 1 + fromRow * kBoardSqSize;
  461.     fromRect.left   = 1 + fromCol * kBoardSqSize;
  462.     fromRect.bottom = fromRect.top  + 32;
  463.     fromRect.right  = fromRect.left + 32;
  464.  
  465.     if (invertBoard) {
  466.         fromRow = 7 - fromRow;
  467.         fromCol = 7 - fromCol;
  468.     }
  469.     fromSq  = START_IBNDS + 10 * fromRow + fromCol;
  470.  
  471.     if (GameStatus(frHndl) != kGameContinues) return;
  472.         /* Game over, so no moves. */
  473.  
  474.     if ((*frHndl)->doc.resync != kIsMove) return;
  475.         /* Don't allow moves until we are resynced. */
  476.  
  477.     numLegalMoves = (*frHndl)->doc.numLegalMoves;
  478.     legalMoves    = (*frHndl)->doc.legalMoves;
  479.  
  480.     for (i = 0; i < numLegalMoves; ++i)
  481.         if ((**legalMoves)[i].moveFrom == fromSq) break;
  482.  
  483.     if (i == numLegalMoves) return;
  484.         /* Clicked on a empty square or on a piece that can't move. */
  485.  
  486.     whosMove = WhosMove(frHndl);
  487.     myColor  = (*frHndl)->doc.myColor;
  488.     OSEventAvail(nullEvent, &option);
  489.     if (option.modifiers & optionKey)
  490.         if (myColor != kMessageDoc) myColor = whosMove;
  491.  
  492.     if ((twoPlayer) && (whosMove != myColor)) return;
  493.         /* It's the other player's turn. */
  494.  
  495.     if ((whosMove == WHITE) && ((*frHndl)->doc.compMovesWhite)) return;
  496.     if ((whosMove == BLACK) && ((*frHndl)->doc.compMovesBlack)) return;
  497.         /* Computer is moving this color, so ignore click. */
  498.  
  499.     SetCursor(*GetCursor(closedHandCursor));
  500.     gCurrentCursor = nil;
  501.  
  502.     releaseLoc.h = releaseLoc.v = 0x4000;
  503.     MoveThePiece(frHndl, fromSq, fromRect, clickLoc, &releaseLoc);
  504.  
  505.     toRow = (releaseLoc.v - kBoardVOffset) / kBoardSqSize;
  506.     toCol = (releaseLoc.h - kBoardHOffset) / kBoardSqSize;
  507.     if (invertBoard) {
  508.         toRow = 7 - toRow;
  509.         toCol = 7 - toCol;
  510.     }
  511.     toSq = START_IBNDS + 10 * toRow + toCol;
  512.  
  513.     for (i = 0; i < numLegalMoves; ++i)
  514.         if (
  515.             ((**legalMoves)[i].moveFrom == fromSq) &&
  516.             ((**legalMoves)[i].moveTo   == toSq)
  517.         ) break;
  518.  
  519.     promotion = QUEEN;        /* If there is a promotion, assume queen. */
  520.  
  521.     if (legalMove = (i < numLegalMoves)) {
  522.  
  523.         if ((toRow == 0) || (toRow == 7)) {        /* Possible pawn promotion... */
  524.  
  525.             piece = (*frHndl)->doc.theBoard[fromSq];
  526.             if (piece < 0) piece = -piece;
  527.  
  528.             if (piece == PAWN) {                /* It is a pawn promotion... */
  529.  
  530.                 if (option.modifiers & shiftKey) promotion = QUEEN;
  531.                 else {
  532.  
  533.                     MakeMove(frHndl, fromSq, toSq, PAWN);
  534.                     ImageDocument(frHndl, true);
  535.                     MakeMove(frHndl, -1, 0, 0);
  536.  
  537.                     promoteDialog = GetCenteredDialog(rPawnPromotion, nil,
  538.                                                       FrontWindow(), (WindowPtr)-1L);
  539.                     if (promoteDialog) {
  540.                         SetPort(promoteDialog);
  541.                         OutlineDialogItem(promoteDialog, 1);
  542.                         DoSetCursor(&qd.arrow);
  543.  
  544.                         for (item = QUEEN;;) {
  545.                             if (promotion != item) {
  546.                                 GetDItem(promoteDialog, promotion + 1, &itemType, &itemHndl, &itemRect);
  547.                                 SetCtlValue((ControlHandle)itemHndl, false);
  548.                             }
  549.  
  550.                             GetDItem(promoteDialog, item + 1, &itemType, &itemHndl, &itemRect);
  551.                             SetCtlValue((ControlHandle)itemHndl, true);
  552.                             promotion = item;
  553.  
  554.                             ModalDialog((ModalFilterProcPtr)KeyEquivFilter, &item);
  555.                             if (item == 1) break;
  556.                             --item;
  557.                         }
  558.                         DisposDialog(promoteDialog);
  559.                         SetPort(window);
  560.                     }
  561.                 }
  562.             }
  563.         }
  564.     }
  565.  
  566.     if (GameStatus(frHndl)) ImageDocument(frHndl, true);
  567.     else {
  568.         if (legalMove) MakeMove(frHndl, fromSq, toSq, promotion);
  569.         ImageDocument(frHndl, true);
  570.         DrawTime(frHndl);
  571.         if (legalMove) AdjustGameSlider(frHndl);
  572.         DrawButtonTitle(frHndl, twoPlayer);
  573.         UpdateGameStatus(frHndl);
  574.         if ((legalMove) && (twoPlayer)) SendGame(frHndl, kIsMove, nil);
  575.         AlertIfGameOver(frHndl);
  576.     }
  577. }
  578.  
  579.  
  580.  
  581. /*****************************************************************************/
  582.  
  583.  
  584.  
  585. extern TheDoc    newDocData;
  586.  
  587. #pragma segment Main
  588. short    AlertIfGameOver(FileRecHndl frHndl)
  589. {
  590.     WindowPtr        oldPort;
  591.     short            status, i, theAlert;
  592.     Str255            gameStatMssg;
  593.     Handle            rsrc;
  594.     long            l;
  595.     static Str255    whichMessage;
  596.  
  597.     theAlert = rGameStat;
  598.  
  599.     if ((status = GameStatus(frHndl)) != kGameContinues) {
  600.  
  601.         if (gComputerResigns) {
  602.             if (!whichMessage[0]) {
  603.                 rsrc = GetResource('STR#', rComputerResigns);
  604.                 whichMessage[0] = **(short **)rsrc;
  605.                 for (i = 1; i <= whichMessage[0]; ++i) whichMessage[i] = i;
  606.             }
  607.             theAlert = rComputerResigns;
  608.             gComputerResigns = false;
  609.             l  = Random();
  610.             l &= 0x0000FFFFL;
  611.             l *= whichMessage[0];
  612.             l /= 0x10000L;
  613.             status = whichMessage[++l];
  614.             whichMessage[l] = whichMessage[whichMessage[0]--];
  615.         }
  616.  
  617.         UpdateGameStatus(frHndl);
  618.         GetIndString(gameStatMssg, theAlert, status);
  619.         ParamText(gameStatMssg, nil, nil, nil);
  620.         DoSetCursor(&qd.arrow);
  621.  
  622.         gStatusTime = TickCount();
  623.         if (((*frHndl)->doc.compMovesWhite) && ((*frHndl)->doc.compMovesBlack))
  624.             status = kGameContinues;
  625.  
  626.         gAlertTimeout = false;
  627.         CenteredAlert(theAlert, (*frHndl)->fileState.window, (ModalFilterProcPtr)statusFilter);
  628.         if (!gAlertTimeout) status = GameStatus(frHndl);
  629.  
  630.         if (status == kGameContinues) {
  631.             oldPort = SetFilePort(frHndl);
  632.             RepositionBoard(frHndl, 0, true);
  633.             UpdateGameStatus(frHndl);
  634.             if ((*frHndl)->doc.twoPlayer) SendGame(frHndl, kResync, nil);
  635.             AdjustGameSlider(frHndl);
  636.             for (i = 0; i < 2; ++i)
  637.                 if ((*frHndl)->doc.timeLeft[i] != -1)
  638.                     (*frHndl)->doc.timeLeft[i] = (*frHndl)->doc.displayTime[i] =
  639.                         (*frHndl)->doc.defaultTime[i];
  640.             (*frHndl)->doc.timerRefTick = TickCount();
  641.             UpdateTime(frHndl, false);
  642.             DrawTime(frHndl);
  643.             SetPort(oldPort);
  644.         }            
  645.     }
  646.  
  647.     return(status);
  648. }
  649.  
  650.  
  651.  
  652. /*****************************************************************************/
  653.  
  654.  
  655.  
  656. #pragma segment Config
  657. pascal Boolean    statusFilter(DialogPtr dlg, EventRecord *event, short *item)
  658. {
  659.     if (AlertFilter(dlg, event, item)) return(true);
  660.     if ((gStatusTime) && (gStatusTime + 600 < TickCount())) {
  661.         gAlertTimeout = true;
  662.         return(true);
  663.     }
  664.  
  665.     return(false);
  666. }
  667.  
  668.  
  669.  
  670.